<template>
  <div class="tab-2">
    <div class="container">
      <van-cell
        title="运动类型"
        :value="sportType || '未选择运动'"
        is-link
        @click="showType = true"
      />
      <van-action-sheet
        v-model="showType"
        :actions="actionsType"
        @select="onSelectType"
        cancel-text="没有想要的？反馈一下😳"
        @cancel="showFeedback = true"
      />
      <van-cell title="运动时长" :value="sportTime || '暂无运动时长'" />
      <div class="time">
        <div class="hours">
          <div class="time-item">{{ hours }}</div>
          <span>时</span>
        </div>
        <div class="minutes">
          <div class="time-item">
            {{ minutes }}
          </div>
          <span>分</span>
        </div>
        <div class="seconds">
          <div class="time-item">
            {{ seconds }}
          </div>
          <span>秒</span>
        </div>
      </div>
      <van-button
        @click="start"
        :type="isStart ? 'danger' : 'info'"
        block
        round
        class="start"
        >{{ isStart ? "暂停" : "👉开始👈" }}</van-button
      >
      <div class="records">
        <h4>记录📋</h4>
        <van-sticky>
          <div class="item-header">
            <div>类型</div>
            <div>时长</div>
            <div>数据</div>
          </div>
        </van-sticky>
        <div class="item" v-for="item in sportList" :key="item.id">
          <div class="type">{{ item.sportType }}</div>
          <div class="duration">
            {{ `${item.hours}:${item.minutes}:${item.seconds}` }}
          </div>
          <div class="data">{{ formatData(item) }}</div>
        </div>
      </div>
    </div>

    <!-- 弹窗（反馈） -->
    <van-overlay :show="showFeedback">
      <div class="wrapper" @click.stop>
        <div class="block">
          <h3>
            反<span>{{ changeIcon ? "🙈" : "🙉" }}</span
            >馈
          </h3>
          <div class="content">
            <van-field
              v-model="message"
              rows="1"
              type="textarea"
              placeholder="留下您的宝贵意见"
              @focus="changeIcon = true"
              @blur="changeIcon = false"
            />
          </div>
          <div class="footer">
            <van-button type="default" size="small" block round @click="cancel"
              >不用了</van-button
            >
            <van-button type="success" size="small" block round @click="submit"
              >提交</van-button
            >
          </div>
        </div>
      </div>
    </van-overlay>

    <!-- 弹窗（运动数据） -->
    <van-overlay :show="showSportData">
      <div class="wrapper" @click.stop>
        <div class="block">
          <h3>运动数据</h3>
          <span class="tip">*仅限计数运动</span>
          <div class="sport-content">
            <span>当前运动：{{ sportType }}</span>
            <van-field
              v-model="sportData"
              type="digit"
              class="sport-data"
              placeholder="填写运动数据（个）"
            />
          </div>
          <div class="footer">
            <van-button
              type="success"
              size="small"
              block
              round
              style="background-color: #409eff; color: #fff"
              @click="submitSport"
              >提交</van-button
            >
          </div>
        </div>
      </div>
    </van-overlay>
  </div>
</template>

<script>
import { addFeedback } from "@/api/mobile/feedback";
import { getLocation } from "@/utils/location";
import userModule from "@/utils/userInfo";
import { Dialog, Notify, Toast } from "vant";
import {
  getSportInfo,
  getSportTypeList,
  refreshSportInfo,
} from "@/api/mobile/sport";
import { compute_distance } from "@/utils/map";
import modifyActivityTime from "@/utils/modify";
export default {
  name: "Tab2View",
  props: ["status", "loading", "toggle"],
  data() {
    return {
      // 运动类型
      sportType: "",
      // 运动时长
      sportTime: "",
      // 显示反馈弹窗
      showFeedback: false,
      // 显示运动类型弹窗
      showType: false,
      // 运动类型列表
      actionsType: [],
      // 反馈内容
      message: "",
      // 是否改变反馈标题图标
      changeIcon: false,
      // 位置信息
      location: [],
      // 是否开始
      isStart: false,
      // 时间
      hours: 0,
      minutes: 0,
      seconds: 0,
      // Web Worker
      worker: null,
      // 位置获取定时器
      locationTimer: null,
      // 是否首次运动
      isFirst: 0,
      // 运动列表
      sportList: [],
      // 用户当天运动id
      sportId: 0,
      // 所选运动的标准
      metricType: "",
      // 运动类型标准id
      metricTypeId: 0,
      // 是否显示运动数据弹窗
      showSportData: false,
      // 运动数据
      sportData: "",
      // 运动类型id
      sportTypeId: 0,
      // 判断跑步运动是否正常启动
      isRun: false,
    };
  },
  created() {
    if (!this.status) {
      Notify({ type: "warning", message: "请先打卡后再来进行今天的运动吧" });
      this.$emit("active", 0);
      return;
    }
    this.getSport();
    this.getSportType();
  },
  mounted() {
    // 使用原生Worker构造函数并正确解析路径
    this.worker = new Worker(
      new URL("@/utils/timer.worker.js", import.meta.url)
    );
    this.worker.onmessage = (e) => {
      let { hours, minutes, seconds } = e.data;
      this.hours = hours;
      this.minutes = minutes;
      this.seconds = seconds;
    };
    // 添加错误处理
    this.worker.onerror = (error) => {
      console.error("Worker error:", error);
      this.$toast("计时器初始化失败");
    };
  },
  watch: {
    // 监视下拉刷新
    loading() {
      if (!this.status) {
        Notify({ type: "warning", message: "请先打卡后再来进行今天的运动吧" });
        return;
        this.$emit("active", 0);
      }
      this.getSport();
      this.getSportType();
    },
    // 监听页面切换
    toggle() {
      if (!this.status) {
        Notify({ type: "warning", message: "请先打卡后再来进行今天的运动吧" });
        this.$emit("active", 0);
        return;
      }
      this.getSport();
      this.getSportType();
    },
  },
  methods: {
    // 获取用户运动信息
    async getSport() {
      const user = userModule.getUser();
      if (!user) {
        Toast("请先登录");
        this.$router.push("/login");
        return;
      }
      const res = await getSportInfo({ id: user.id });
      const { id, hours, minutes, seconds, sportList, isFirst } = res.data;
      this.sportId = id;
      this.sportList = sportList || [];
      this.isFirst = isFirst;
      this.sportTime = `${hours}小时${minutes}分钟${seconds}秒`;
      // 更新用户活动状态
      modifyActivityTime();
    },
    // 格式化运动数据
    formatData(item) {
      return item.data + this.judgmentType(item.metricType);
    },
    judgmentType(type) {
      switch (type) {
        case "distance":
          return "km";
        case "count":
          return "个";
        default:
          return "--";
      }
    },
    // 获取运动类型
    async getSportType() {
      const res = await getSportTypeList();
      res.data.forEach((obj) => {
        obj.name = obj.type;
      });
      this.actionsType = res.data;
    },
    // 选择运动
    onSelectType(item) {
      if (this.isStart) {
        Notify({
          type: "danger",
          message: "当前运动未结束，请结束后再进行选择",
        });
        return;
      }
      // 默认情况下点击选项时不会自动收起
      // 可以通过 close-on-click-action 属性开启自动收起
      this.showType = false;
      this.sportType = item.name;
      this.metricType = item.metricType;
      this.sportTypeId = item.id;
      this.metricTypeId = item.metricTypeId;

      this.hours = 0;
      this.minutes = 0;
      this.seconds = 0;
      if (this.sportList !== null) {
        this.sportList.forEach((obj) => {
          if (obj.sportType === this.sportType) {
            this.hours = obj.hours;
            this.minutes = obj.minutes;
            this.seconds = obj.seconds;
          }
        });
      }
    },
    // 取消反馈
    cancel() {
      this.message = "";
      this.showFeedback = false;
    },
    // 提交反馈
    async submit() {
      if (!this.message) {
        Toast("您还未留下意见哦💬");
        return;
      }
      await addFeedback({
        content: this.message,
      });
      Toast({
        duration: 3000,
        message: "提交成功\n反馈结果可在我的-设置-反馈中心进行查看",
      });
      this.message = "";
      this.showFeedback = false;
    },
    // 开始
    async start() {
      if (!this.status) {
        Notify({ type: "warning", message: "请先打卡后再来进行今天的运动吧" });
        this.$emit("active", 0);
        return;
      }
      if (!this.sportType) {
        Notify({ type: "warning", message: "请先选择运动类型" });
        return;
      }
      if (this.isFirst === 0) {
        Dialog.confirm({
          message: "是否开启今天的运动计时？该提示仅首次开始时提示。",
        })
          .then(async () => {
            console.log("开始运动");
            this.isStart = true;
            this.worker.postMessage({
              type: "start",
              hours: this.hours,
              minutes: this.minutes,
              seconds: this.seconds,
            });
            if (this.metricType === "distance") {
              Toast({
                duration: 3000,
                type: "html",
                message:
                  "建议关闭省电模式使用！请开启手机定位，否则可能将无法获取位置信息",
              });
              await this.getLocation();
            }
            this.isFirst = 1;
            if (this.metricType === "distance" && this.isRun) {
              localStorage.setItem("start_sport", true);
            } else if (this.metricType !== "distance") {
              localStorage.setItem("start_sport", true);
            }
          })
          .catch(() => console.log("已取消"));
      } else {
        if (this.isStart) {
          // 关闭逻辑
          this.isStart = false;
          this.worker.postMessage({
            type: "stop",
            hours: 0,
            minutes: 0,
            seconds: 0,
          });
          if (this.metricType === "count") {
            this.showSportData = true;
          } else {
            this.submitSport();
          }
          localStorage.setItem("start_sport", false);
          console.log("已关闭");
        } else {
          // 开启逻辑
          this.isStart = true;
          this.worker.postMessage({
            type: "start",
            hours: this.hours,
            minutes: this.minutes,
            seconds: this.seconds,
          });
          if (this.metricType === "distance") {
            Toast({
              duration: 3000,
              type: "html",
              message:
                "建议关闭省电模式使用！请开启手机定位，否则可能将无法获取位置信息",
            });
            await this.getLocation();
          }
          if (this.metricType === "distance" && this.isRun) {
            localStorage.setItem("start_sport", true);
          } else if (this.metricType !== "distance") {
            localStorage.setItem("start_sport", true);
          }
          console.log("已开启");
        }
      }
    },
    // 提交运动
    async submitSport() {
      if (this.metricType === "distance") {
        clearInterval(this.locationTimer);
        const res = await compute_distance(this.location, "km");
        this.sportData = res;
        this.location = [];
        // 累加数据
        if (this.sportList !== null && this.sportList.length > 0) {
          this.sportList.forEach((item) => {
            if (item.sportType === this.sportType) {
              this.sportData = +item.data + +this.sportData;
            }
          });
        }
        this.sportData = this.sportData.toFixed(2);
      } else if (this.metricType === "count") {
        if (this.sportData === "") {
          Toast("您还未输入数据哦🤔");
          return;
        }
        if (this.sportData.startsWith("0") && this.sportData.length > 1) {
          Toast("请输入正确的数据哦🤔");
          return;
        }
        // 累加数据
        if (this.sportList !== null && this.sportList.length > 0) {
          this.sportList.forEach((item) => {
            if (item.sportType === this.sportType)
              this.sportData = +item.data + +this.sportData;
          });
        }
        this.showSportData = false;
      } else {
        this.sportData = "";
      }
      const list = [
        {
          sportsTypeId: this.sportTypeId,
          sportType: this.sportType,
          metricTypeId: this.metricTypeId,
          hours: this.hours,
          minutes: this.minutes,
          seconds: this.seconds,
          data: this.sportData,
        },
      ];
      const { hours, minutes, seconds } = this.computeTime();
      this.sportTime = `${hours}小时${minutes}分钟${seconds}秒`;
      const data = {
        id: this.sportId,
        hours,
        minutes,
        seconds,
        list,
      };
      await refreshSportInfo(data);
      this.sportData = "";
      this.getSport();
    },
    // 计算时间
    computeTime() {
      // 计算总时间
      let totalTime = 0;
      if (this.sportList !== null && this.sportList.length > 0) {
        this.sportList.forEach((obj) => {
          if (obj.sportType !== this.sportType) {
            totalTime += obj.hours * 3600 + obj.minutes * 60 + obj.seconds;
          }
        });
      }
      // 计算当前运动时间
      const currentTime = this.hours * 3600 + this.minutes * 60 + this.seconds;
      totalTime += currentTime;
      return {
        hours: Math.floor(totalTime / 3600),
        minutes: Math.floor((totalTime % 3600) / 60),
        seconds: totalTime % 60,
      };
    },
    // 获取定位
    async getLocation() {
      this.isRun = true;
      const res = await getLocation();
      if (!res) {
        this.isStart = false;
        this.isRun = false;
        this.worker.postMessage({
          type: "stop",
        });
        // 防止意料之外的情况无法将运动状态置为false
        localStorage.setItem("start_sport", false);
        return;
      }
      // 每隔八秒获取一次位置信息
      this.location.push(res);
      this.locationTimer = setInterval(async () => {
        this.location.push(await getLocation());
      }, 8000);
    },
  },
};
</script>

<style lang="less" scoped>
.tab-2 {
  min-height: 100vh;
  .container {
    .time {
      margin: 10px;
      display: flex;
      justify-content: space-evenly;
      .hours,
      .minutes,
      .seconds {
        display: flex;
        align-items: center;
        width: 100px;
        height: 100px;
        .time-item {
          width: 60px;
          height: 60px;
          text-align: center;
          line-height: 60px;
          font-size: 22px;
          border-radius: 10px;
          box-shadow: 0 0 3px #999;
        }
        span {
          flex: 1;
          text-align: center;
        }
      }
    }
    .start {
      margin: 30px auto;
      width: 70%;
      height: 40px;
      font-size: 18px;
    }
    .records {
      margin: 0 20px;
      h4 {
        font-size: 18px;
        padding-bottom: 4px;
      }
      .item-header {
        display: flex;
        height: 30px;
        text-align: center;
        border-radius: 8px;
        box-shadow: 0 1px 2px #ccc;
        div:nth-child(1),
        div:nth-child(2),
        div:nth-child(3) {
          width: 33%;
        }
      }
      .item {
        display: flex;
        margin: 10px 0;
        box-shadow: 0 0 4px #ccc;
        border-radius: 10px;
        text-align: center;
        height: 40px;
        line-height: 40px;
        .type,
        .duration,
        .data {
          width: 33%;
        }
      }
    }
  }
  .wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
  }
  .block {
    position: relative;
    width: 310px;
    min-height: 200px;
    border-radius: 10px;
    background-color: #fff;
    h3 {
      margin: 20px 0 10px;
      text-align: center;
    }
    .content {
      margin: 0 10px;
      border: 1px solid #ddd;
      border-radius: inherit;
      height: 60%;
    }
    .tip {
      display: block;
      text-align: right;
      margin-right: 20px;
      font-size: 10px;
      color: rgba(255, 0, 0, 0.5);
    }
    .sport-content {
      margin: 0 20px;
      .sport-data {
        margin-top: 10px;
        border-radius: 10px;
        box-shadow: 0 0 3px #ccc;
      }
    }
    .footer {
      display: flex;
      justify-content: space-around;
      margin: 10px;
    }
  }
}
/deep/.van-cell {
  height: 100%;
  border-radius: inherit;
  .van-field__body {
    height: 100%;
    .van-field__control {
      height: 100%;
    }
  }
}
/deep/.van-button {
  width: 48%;
  box-shadow: 0 0 4px #ccc;
  border: none;
  &:nth-child(2) {
    color: #fff;
    background-color: #409eff;
  }
}
/deep/.van-pull-refresh__track {
  min-height: calc(100vh - 44px);
}
/deep/.van-tabs__content {
  margin-bottom: 44px;
}
</style>